package travianBot;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.htmlcleaner.CommentToken;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

public class ResourceManager {

	static Pattern haendlerPattern = Pattern.compile(".*carry = (\\d*);");
	
	/**
	 * calculate how much a supplier should send
	 * @param supplier
	 * @param collectorList
	 * @param traderCapacity
	 * @param traderCount
	 * @return
	 * @throws TravianBotException 
	 */
	public static HashMap<String,Integer> calculateMarketSupplyValues(
			HashMap<String,ResourceCounter> supplier,
			Collection<ResourceCounter> collectorList, 
			TraderDetails traderDetails , int traderCount, int villageResourceMin) throws TravianBotException{	
					
		ResourceCounter currentResourceCounter = null;
		ResourceCounter supplierResourceCounter = null;
		HashMap<String,Integer> incrementMap = new HashMap<String,Integer>();				
		
		if( traderDetails.free < traderCount){
			throw new TravianBotException("not enough traders available");
		}
		
		// keep track of the original list of collectorCounters, to refer to later
		ArrayList<ResourceCounter> originalCollectorList = new ArrayList<ResourceCounter>();
		for (ResourceCounter ResourceCounter : collectorList) {
			originalCollectorList.add(ResourceCounter);
		}
		
		// initialise the return map, with a zero entry for each type of resource
		for (int i = 0; i < Village.RESOURCE_NAME_ARRAY.length; i++) {
			incrementMap.put(Village.RESOURCE_NAME_ARRAY[i], 0);
		}
		
		boolean allSpent = false;
		boolean spentSomething = false;
		// for every trader on offer
		for (; 0 < traderCount && !allSpent; traderCount--) {
			currentResourceCounter = null;
			supplierResourceCounter = null;
			spentSomething = false;
			//
			// figure out which resource to donate
			//			
			int remainingSpace=0;
			
			// get the entry with the least amount of resource. there are 4 only types of resource			
			for(int i=0; i<4 && collectorList.size() > 0;i++){
				currentResourceCounter = minCurrent(collectorList);
				remainingSpace = currentResourceCounter.getCapacity() - currentResourceCounter.getCurrent();
				supplierResourceCounter = supplier.get(currentResourceCounter.getResourceName());
				
				// the supplier can't afford it - or there's no space left
				if(supplierResourceCounter.getCurrent() < traderDetails.capacity|| 
						villageResourceMin >= supplierResourceCounter.getCurrent() || 
						remainingSpace == 0){					
					// stop looking at it
					collectorList.remove(currentResourceCounter);					
				}else{
					// we're good to go
					spentSomething = true;
					break;
				}
			}
						
			//
			// work out how much to assign to it
			// 			
			int delta;
			if(remainingSpace > 0 && spentSomething){
				if(remainingSpace < traderDetails.capacity){
					delta = remainingSpace;
				}else{
					delta = traderDetails.capacity;
				}
				currentResourceCounter.setCurrent(currentResourceCounter.getCurrent()+delta);
				supplierResourceCounter.setCurrent(supplierResourceCounter.getCurrent()-delta);
			}			
		}
		
		//
		// setup the return structure
		//	
		boolean anythingToTrade = false;
		//for (ResourceCounter ResourceCounter : collectorList) {
		for (ResourceCounter ResourceCounter : originalCollectorList){
			int amountToTrade = ResourceCounter.getCurrent() - ResourceCounter.getOriginalCurrent();
			incrementMap.put(ResourceCounter.getResourceName(), amountToTrade);
			if(amountToTrade > 0){
				anythingToTrade = true;
			}
		}			
		
		if(!anythingToTrade){
			incrementMap = null;
		}
		return incrementMap;
	}
	
	public static TraderDetails collectTraderDetails(String htmlContent) throws TravianBotException{
		TraderDetails traderDetails=new TraderDetails();
		
		//table id="target_select
		HtmlCleaner htmlCleaner = new HtmlCleaner();

		try {
			TagNode parentNode = htmlCleaner.clean(htmlContent);
			Object[] nodeArray = parentNode.evaluateXPath("//table[@id='target_select']/tbody/tr/td[@class='mer']");
			StringBuffer	nodeText;

			for (int i = 0; i < nodeArray.length; i++) {
				TagNode resourceTDNode = (TagNode)nodeArray[i];	
				nodeText = resourceTDNode.getText();
				//Merchants 20/20
				String[] bigSplit = nodeText.toString().split(" ");
				String[] traders = bigSplit[1].split("/");
				traderDetails.free = Integer.parseInt(traders[0]);
				traderDetails.total = Integer.parseInt(traders[1]);
			}
			
			nodeArray = parentNode.evaluateXPath("//div[@id='build']");
			
			for (int i = 0; i < nodeArray.length; i++) {
				TagNode resourceTDNode = (TagNode)nodeArray[i];	
				Object[] bNodeArray = resourceTDNode.evaluateXPath("//b");
				//assume there's only one bold node and it's child has the trader capacity in it.
				TagNode  boldNode = (TagNode)bNodeArray[0]; // bold node
				String stringCapacity = boldNode.getText().toString();
				traderDetails.capacity = Integer.parseInt(stringCapacity);
				
			}							
		}catch (XPatherException e) {
			throw new TravianBotException("problems collecting the number of free traders",e);
		}catch (IOException ioe){
			throw new TravianBotException("problems collecting the number of free traders",ioe);
		}
		return traderDetails;
	}
	
	private static ResourceCounter  minCurrent(Collection<ResourceCounter> counterList){
		ResourceCounter minCounter = counterList.iterator().next();
		
		for (ResourceCounter resourceCounter : counterList) {
			if(resourceCounter.getCurrent() < minCounter.getCurrent()){
				minCounter = resourceCounter;
			}
		}
		return minCounter;
	}
}
